package com.zzyl.nursing.service.impl;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.CheckOutApplyDto;
import com.zzyl.nursing.dto.CheckOutFeeDetailDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.vo.CheckOutDetailVo;
import com.zzyl.nursing.vo.CheckOutFeeDetailVo;
import com.zzyl.nursing.vo.CheckOutVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.service.ICheckOutService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 退住办理Service业务层处理
 *
 * @Author: Zhy
 * @Date: 2025-07-13
 */
@Service
@RequiredArgsConstructor
public class CheckOutServiceImpl extends ServiceImpl<CheckOutMapper, CheckOut> implements ICheckOutService {

    private final CheckOutMapper checkOutMapper;
    private final CheckOutFeeDetailMapper checkOutFeeDetailMapper;
    private final CheckInMapper checkInMapper; // Added CheckInMapper
    private final BedMapper bedMapper; // Added BedMapper
    private final ElderMapper elderMapper; // Added ElderMapper

    private static int sort = 0;

    /**
     * 查询退住办理
     *
     * @param id 退住办理主键
     * @return 退住办理
     */
    @Override
    public CheckOut selectCheckOutById(Long id) {
        return checkOutMapper.selectById(id);
    }

    /**
     * 查询退住办理列表
     *
     * @param checkOut 退住办理
     * @return 退住办理
     */
    @Override
    public List<CheckOut> selectCheckOutList(CheckOut checkOut) {
        return checkOutMapper.selectCheckOutList(checkOut);
    }

    /**
     * 新增退住办理
     *
     * @param checkOut 退住办理
     * @return 结果
     */
    @Override
    public int insertCheckOut(CheckOut checkOut) {
        return checkOutMapper.insertCheckOut(checkOut);
    }

    /**
     * 修改退住办理
     *
     * @param checkOut 退住办理
     * @return 结果
     */
    @Override
    public int updateCheckOut(CheckOut checkOut) {
        return checkOutMapper.updateById(checkOut);
    }

    /**
     * 批量删除退住办理
     *
     * @param ids 需要删除的退住办理主键
     * @return 结果
     */
    @Override
    public int deleteCheckOutByIds(Long[] ids) {
        return checkOutMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除退住办理信息
     *
     * @param id 退住办理主键
     * @return 结果
     */
    @Override
    public int deleteCheckOutById(Long id) {
        return checkOutMapper.deleteById(id);
    }

    /**
     * 申请退住
     *
     * @param checkOutApplyDto 退住申请DTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void apply(CheckOutApplyDto checkOutApplyDto) {
        // 1. 验证是否已有退住申请
        validateExistingCheckOut(checkOutApplyDto.getCheckInId());

        // 2. 新增退住记录
        Long checkOutId = addCheckOut(checkOutApplyDto);

        // 3. 新增费用明细
        addFeeDetails(checkOutId, checkOutApplyDto.getFeeDetailList());
    }

    /**
     * 退住详情
     *
     * @param id 退住记录ID
     * @return 退住详情
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CheckOutDetailVo getCheckOutInfo(Long id) {
        // 1. 查询退住基本信息
        CheckOut checkOut = checkOutMapper.selectById(id);
        if (ObjectUtil.isNull(checkOut)) {
            throw new BaseException("退住记录不存在");
        }

        // 2. 查询费用明细
        List<CheckOutFeeDetail> feeDetailList = checkOutFeeDetailMapper.selectFeeDetailByCheckOutId(id);

        // 3. 封装退住详情
        CheckOutDetailVo checkOutDetailVo = new CheckOutDetailVo();
        
        // 封装退住基本信息
        CheckOutVo checkOutVo = BeanUtil.toBean(checkOut, CheckOutVo.class);
        checkOutDetailVo.setCheckOutVo(checkOutVo);
        
        // 封装费用明细
        List<CheckOutFeeDetailVo> feeDetailVoList = BeanUtil.copyToList(feeDetailList, CheckOutFeeDetailVo.class);
        checkOutDetailVo.setFeeDetailList(feeDetailVoList);

        return checkOutDetailVo;
    }

    /**
     * 审批退住申请
     *
     * @param id 退住记录ID
     * @param status 审批状态(1=已批准,3=已拒绝)
     * @param approvalRemark 审批备注
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(Long id, Integer status, String approvalRemark) {
        CheckOut checkOut = checkOutMapper.selectById(id);
        if (ObjectUtil.isNull(checkOut)) {
            throw new BaseException("退住记录不存在");
        }

        if (checkOut.getStatus() != 0) {
            throw new BaseException("该退住申请已被处理，无法重复审批");
        }

        checkOut.setStatus(status);
        checkOut.setApprovalTime(LocalDateTime.now());
        checkOut.setApprovalRemark(approvalRemark);
        // TODO: 设置审批人（从当前登录用户获取）
        checkOut.setApprover("admin");

        checkOutMapper.updateById(checkOut);

        if (status == 1) { // 审批通过
            // 更新入住表状态为已退住
            CheckIn checkIn = checkInMapper.selectById(checkOut.getCheckInId());
            if (checkIn != null) {
                checkIn.setStatus(1); // 1=已退住
                checkInMapper.updateById(checkIn);
                
                // 释放床位：通过床位号查找并释放
                releaseBedByNumber(checkIn.getBedNumber());
                
                // 清除老人的床位关联
                clearElderBedAssociation(checkIn.getElderId());
            }
        }
    }

    /**
     * 完成退住
     *
     * @param id 退住记录ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeCheckOut(Long id) {
        CheckOut checkOut = checkOutMapper.selectById(id);
        if (ObjectUtil.isNull(checkOut)) {
            throw new BaseException("退住记录不存在");
        }

        if (checkOut.getStatus() != 1) {
            throw new BaseException("只有已批准的退住申请才能完成退住");
        }

        // 更新退住状态为已退住
        checkOut.setStatus(2);
        checkOutMapper.updateById(checkOut);

        // TODO: 这里可以添加与其他模块的交互逻辑
        // 1. 更新入住记录状态为已退住
        // 2. 更新老人状态为已退住
        // 3. 释放床位
        // 4. 终止合同
    }

    /**
     * 撤销退住申请
     *
     * @param id 退住记录ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void revokeCheckOut(Long id) {
        CheckOut checkOut = checkOutMapper.selectById(id);
        if (ObjectUtil.isNull(checkOut)) {
            throw new BaseException("退住记录不存在");
        }

        if (checkOut.getStatus() != 0) {
            throw new BaseException("只有申请中的退住记录可以撤销");
        }

        // 删除退住记录
        checkOutMapper.deleteById(id);
        
        // 删除相关的费用明细
        checkOutFeeDetailMapper.deleteByCheckOutId(id);
    }

    /**
     * 级联删除退住和入住数据
     *
     * @param checkOutId 退住记录ID
     * @param checkInId 入住记录ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCheckOutAndCheckIn(Long checkOutId, Long checkInId) {
        CheckOut checkOut = checkOutMapper.selectById(checkOutId);
        if (ObjectUtil.isNull(checkOut)) {
            throw new BaseException("退住记录不存在");
        }

        if (checkOut.getStatus() != 2) {
            throw new BaseException("只有已退住状态的记录可以删除");
        }

        // 删除退住记录
        checkOutMapper.deleteById(checkOutId);
        
        // 删除相关的费用明细
        checkOutFeeDetailMapper.deleteByCheckOutId(checkOutId);
        
        // 删除入住记录
        if (checkInId != null) {
            checkInMapper.deleteById(checkInId);
        }
    }

    /**
     * 验证是否已有退住申请
     */
    private void validateExistingCheckOut(Long checkInId) {
        CheckOut existingCheckOut = checkOutMapper.selectCheckOutByCheckInId(checkInId);
        if (ObjectUtil.isNotNull(existingCheckOut)) {
            throw new BaseException("该入住记录已有退住申请，请勿重复申请");
        }
    }

    /**
     * 新增退住记录
     */
    private Long addCheckOut(CheckOutApplyDto checkOutApplyDto) {
        if (checkOutApplyDto.getCheckInId() == null) {
            throw new BaseException("入住记录ID不能为空，请先选择老人");
        }
        CheckOut checkOut = BeanUtil.toBean(checkOutApplyDto, CheckOut.class);
        checkOut.setStatus(0); // 申请中
        checkOut.setSettlementStatus(0); // 未结算
        checkOut.setContractTermination(0); // 未终止
        checkOut.setSortOrder(sort++);
        checkOut.setElderName(checkOutApplyDto.getElderName());
        checkOut.setIdCardNo(checkOutApplyDto.getIdCardNo()); // 设置身份证号
        checkOut.setCheckInId(checkOutApplyDto.getCheckInId()); // 显式设置入住记录ID
        checkOut.setBedNumber(checkOutApplyDto.getBedNumber()); // 显式设置床位号
        
        // 设置退住日期，如果前端没有传递则使用当前时间
        if (checkOutApplyDto.getCheckOutDate() != null) {
            checkOut.setCheckOutDate(checkOutApplyDto.getCheckOutDate());
        } else {
            checkOut.setCheckOutDate(LocalDateTime.now());
        }

        // 设置创建人
        checkOut.setCreateBy("admin"); // 默认admin

        // 添加调试日志
        System.out.println("CheckOutApplyDto checkInId: " + checkOutApplyDto.getCheckInId());
        System.out.println("CheckOut checkInId: " + checkOut.getCheckInId());

        // 使用自定义的insert方法，确保elder_name字段能正确插入
        checkOutMapper.insertCheckOut(checkOut);
        return checkOut.getId();
    }

    /**
     * 新增费用明细
     */
    private void addFeeDetails(Long checkOutId, List<CheckOutFeeDetailDto> feeDetailList) {
        if (ObjectUtil.isNotEmpty(feeDetailList)) {
            for (CheckOutFeeDetailDto feeDetailDto : feeDetailList) {
                CheckOutFeeDetail feeDetail = BeanUtil.toBean(feeDetailDto, CheckOutFeeDetail.class);
                feeDetail.setCheckOutId(checkOutId);
                checkOutFeeDetailMapper.insert(feeDetail);
            }
        }
    }

    /**
     * 释放床位
     *
     * @param bedNumber 床位号
     */
    private void releaseBed(String bedNumber) {
        // 根据床位号查找床位记录
        LambdaQueryWrapper<Bed> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Bed::getBedNumber, bedNumber);
        Bed bed = bedMapper.selectOne(wrapper);
        
        if (bed != null) {
            bed.setBedStatus(0); // 0=未入住
            bedMapper.updateById(bed);
        }
    }

    /**
     * 释放床位
     *
     * @param bedId 床位ID
     */
    private void releaseBedById(Long bedId) {
        if (bedId == null) return;
        Bed bed = bedMapper.selectById(bedId);
        if (bed != null) {
            bed.setBedStatus(0); // 0=未入住
            bedMapper.updateById(bed);
        }
    }

    /**
     * 释放床位
     *
     * @param bedNumber 床位号
     */
    private void releaseBedByNumber(String bedNumber) {
        if (bedNumber == null) return;
        LambdaQueryWrapper<Bed> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Bed::getBedNumber, bedNumber);
        Bed bed = bedMapper.selectOne(wrapper);
        if (bed != null) {
            bed.setBedStatus(0); // 0=未入住
            bedMapper.updateById(bed);
        }
    }

    /**
     * 清除老人的床位关联
     *
     * @param elderId 老人ID
     */
    private void clearElderBedAssociation(Long elderId) {
        // 根据老人ID查找老人记录
        LambdaQueryWrapper<Elder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Elder::getId, elderId);
        Elder elder = elderMapper.selectOne(wrapper);
        
        if (elder != null) {
            elder.setBedId(null);
            elder.setBedNumber(null);
            elder.setStatus(5); // 5=已退住
            elderMapper.updateById(elder);
        }
    }
} 